package gis

import (
	"fmt"
	"math"
	"strconv"
)

type GisPoint struct {
	Lng float64
	Lat float64
}

type GisGrid struct {
	Id     int64
	Center GisPoint
	L      float64 // 单位: KM
	LT     GisPoint
	RT     GisPoint
	RB     GisPoint
	LB     GisPoint
	PT     GisPoint
}

func NewGisGrid(l float64) *GisGrid {
	rval := &GisGrid{
		L: l,
	}
	return rval
}

func (this *GisPoint) Equal(dst *GisPoint) bool {
	return this.Lat == dst.Lat && this.Lng == dst.Lng
}

func (this *GisPoint) CopyFrom(dst *GisPoint) {
	this.Lat = dst.Lat
	this.Lng = dst.Lng
}

func (this GisPoint) String() string {
	return fmt.Sprintf("%.6f %.6f", this.Lng, this.Lat)
}

func (this *GisGrid) NextGridLng() *GisGrid {
	rval := NewGisGrid(this.L)
	// 每个网格lng和lat度数
	grdlng := rval.L * _LNG_1KM
	rval.Calculate(this.Center.Lng+grdlng, this.Center.Lat)
	return rval
}

func (this *GisGrid) NextGridLat() *GisGrid {
	rval := NewGisGrid(this.L)
	// 每个网格lng和lat度数
	grdlat := _LAT_1KM * rval.L
	rval.Calculate(this.Center.Lng, this.Center.Lat+grdlat)
	return rval
}

func (this *GisGrid) MakeCenterGGAText(quality int64) string {
	nmea := NewNMEA()
	//模版
	nmea.ParseText("$GNGGA,010918.00,3025.36715396,N,11427.95302424,E,2,12,0.9,28.743,M,-13.869,M,85.0,0129*71")
	nmea.Type = "GPGGA"
	nmea.SetLng(this.Center.Lng)
	nmea.SetLat(this.Center.Lat)
	nmea.Quality = strconv.FormatInt(quality, 10)
	nmea.UpdateUTCTime()
	return nmea.Encode()
}

func (this *GisGrid) Calculate(lng, lat float64) {
	this.PT.Lng = lng
	this.PT.Lat = lat

	// 每个网格lng和lat度数
	grdlng := _LNG_1KM * this.L
	grdlat := _LAT_1KM * this.L

	// 在第几个网格里面
	lngN := int32(math.Trunc(lng / grdlng))
	latN := int32(math.Trunc(lat / grdlat))
	this.Id = int64(lngN)<<32 + int64(latN)

	// LB点
	lng1 := float64(lngN) * grdlng
	lat1 := float64(latN) * grdlat

	// 中心点
	this.Center.Lng = lng1 + grdlng/2.0
	this.Center.Lat = lat1 + grdlat/2.0

	// 区域的LeftTop点
	this.LT.Lng = lng1
	this.LT.Lat = lat1 + grdlat

	// 区域的RightTop点
	this.RT.Lng = lng1 + grdlng
	this.RT.Lat = lat1 + grdlat

	// 区域的RightBottom点
	this.RB.Lng = lng1 + grdlng
	this.RB.Lat = lat1

	// 区域的LeftBottom点
	this.LB.Lng = lng1
	this.LB.Lat = lat1
}
